package cn.wolfcode.cloud.shop.web.controller;

import cn.wolfcode.cloud.shop.anno.UserParam;
import cn.wolfcode.cloud.shop.consts.MQConstants;
import cn.wolfcode.cloud.shop.domain.OrderInfo;
import cn.wolfcode.cloud.shop.domain.User;
import cn.wolfcode.cloud.shop.exception.BusinessException;
import cn.wolfcode.cloud.shop.feign.UserFeignApi;
import cn.wolfcode.cloud.shop.mq.msg.CreateOrderMsg;
import cn.wolfcode.cloud.shop.redis.SeckillRedisKey;
import cn.wolfcode.cloud.shop.resp.Result;
import cn.wolfcode.cloud.shop.resp.SeckillServerCodeMsg;
import cn.wolfcode.cloud.shop.service.IOrderInfoService;
import cn.wolfcode.cloud.shop.service.ISeckillGoodService;
import cn.wolfcode.cloud.shop.service.ISeckillOrderService;
import cn.wolfcode.cloud.shop.util.CookieUtil;
import cn.wolfcode.cloud.shop.vo.SeckillGoodsVo;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Administrator
 */
@RestController
@RequestMapping("/orders")
public class OrderInfoController {

    @Autowired
    private UserFeignApi userFeignApi;

    @Autowired
    private ISeckillGoodService seckillGoodService;

    @Autowired
    private ISeckillOrderService seckillOrderService;

    @Autowired
    private IOrderInfoService orderInfoService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    public static final Map<Long,Boolean> STOCK_OVER_FLAG = new ConcurrentHashMap<>();


    /**
     * 优化前:
     *  qps:532/sec
     * 优化后:
     *  qps:875/sec
     * @param seckillId
     * @param user
     * @return
     */
    @RequestMapping("/seckill")
    public Result<String> doSeckill(Long seckillId,String uuid, @UserParam User user){
//        Result<User> userResult = userFeignApi.findByToken(token);
//        User user = userResult.getData();
//        //1.判断用户是否登录
//        if(userResult == null || userResult.hasError()){
//            throw new BusinessException(SeckillServerCodeMsg.USER_NOT_LOGIN);
//        }
        //1.判断用户是否登录
        if(user == null){
            throw new BusinessException(SeckillServerCodeMsg.USER_NOT_LOGIN);
        }

        Boolean stockOver = STOCK_OVER_FLAG.get(seckillId);
        if(stockOver != null && stockOver){
            throw new BusinessException(SeckillServerCodeMsg.OUT_OF_STOCK);
        }

        //获取秒杀商品
        SeckillGoodsVo seckillGoodsVo = seckillGoodService.queryByIdInCache(seckillId);
        if(seckillGoodsVo == null){
            throw new BusinessException(SeckillServerCodeMsg.OP_ERROR);
        }

        //2.判断当前活动是否在活动时间范围内
        Date now = new Date();

        if(now.compareTo(seckillGoodsVo.getStartDate())<0){
            throw new BusinessException(SeckillServerCodeMsg.SECKILL_NOT_START);
        }

        if(now.compareTo(seckillGoodsVo.getEndDate())>=0){
            throw new BusinessException(SeckillServerCodeMsg.SECKILL_IS_STOP);
        }

        //3.判断用户在该秒杀活动写是否已经下过单
//        SeckillOrder seckillOrder = seckillOrderService.queryByUserIdAndSeckillId(user.getId(),seckillId);
//        if(seckillOrder != null){
//            throw new BusinessException(SeckillServerCodeMsg.REPEATE_ORDER_ERROR);
//        }
        Boolean member = redisTemplate.opsForSet().isMember(SeckillRedisKey.SECKILL_ORDERS_SET.getRealKey(seckillId + ""), user.getId() + "");
        if(member == null || member){
            throw new BusinessException(SeckillServerCodeMsg.REPEATE_ORDER_ERROR);
        }


        //4.判断商品库存是否充足
        Long stock = redisTemplate.opsForHash().increment(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(""), seckillId + "", -1);
        if(stock < 0){
            STOCK_OVER_FLAG.put(seckillId,true);
            throw new BusinessException(SeckillServerCodeMsg.OUT_OF_STOCK);
        }
//        if(seckillGoodsVo.getStockCount() < 1){
//            throw new BusinessException(SeckillServerCodeMsg.OUT_OF_STOCK);
//        }

        //5.创建订单
//        String orderNo = orderInfoService.doSeckill(seckillGoodsVo,user.getId());
        rocketMQTemplate.syncSend(MQConstants.CREATE_SECKILL_ORDER_DEST,new CreateOrderMsg(seckillGoodsVo.getId(),user.getId(),uuid));


        //6.返回订单编号
        return Result.success("正在排队中,请耐心等待!");
    }

    @GetMapping("/{orderNo}")
    public Result<OrderInfo> queryByOrderNo(@PathVariable("orderNo") String orderNo,@CookieValue(name = CookieUtil.TOKEN_IN_COOKIE_NAME,required = false) String token){
        Result<User> userResult = userFeignApi.findByToken(token);
        if(userResult == null || userResult.hasError() || userResult.getData() == null){
            throw new BusinessException(SeckillServerCodeMsg.USER_NOT_LOGIN);
        }
        return Result.success(orderInfoService.queryByOrderNo(orderNo));
    }
}
